Skip to content

3/5 refactor: pass durations dict into algorithms#122

Open
vokracko wants to merge 3 commits intojerry-git:masterfrom
vokracko:feat/algorithm-signature-durations-dict
Open

3/5 refactor: pass durations dict into algorithms#122
vokracko wants to merge 3 commits intojerry-git:masterfrom
vokracko:feat/algorithm-signature-durations-dict

Conversation

@vokracko
Copy link
Copy Markdown

@vokracko vokracko commented Apr 29, 2026

Third of five stacked PRs that fix #25.

Motivation. The next PR (4/5) will move within-group ordering out of the algorithms and into the plugin. Doing that cleanly first requires the algorithms to take a single, tight data input. Today's signature (splits, items, durations) mixes the test list with the lookup dict; subsequent steps benefit from a single dict[Item, float] argument that pairs items with their resolved durations up front.

What changes. AlgorithmBase.__call__ takes (splits, durations: dict[Item, float]) instead of (splits, items, durations). The previously-private _get_items_with_durations helper is promoted to public compute_durations, with the two single-call-site helpers it used (_remove_irrelevant_durations, _get_avg_duration_per_test) inlined. The plugin builds the dict once via compute_durations and passes it to the chosen algorithm.

No observable behaviour change.

⚠️ Subclasses of AlgorithmBase need to update — the new signature is (splits, durations), and compute_durations(items, cached_durations) builds the dict the same way the plugin does.

Stack.

The previous setup relied on pytest-cov (``--cov pytest_split
--cov tests`` in addopts) which has a long-standing limitation when
measuring a pytest plugin: the plugin imports happen during pytest's
plugin discovery, *before* pytest-cov starts tracing. Anything that
runs at import time (class bodies, decorators, type aliases, enum
definitions) is reported as uncovered even though it obviously
executed - the plugin wouldn't load otherwise. The
``CoverageWarning: Module pytest_split was previously imported, but
not measured`` made that explicit.

The cookiecutter template the project was generated from worked
around this by adding ``--cov tests`` to the addopts, inflating the
denominator with 100%-covered test files so the average reached 90%.
That pulled the number up but stopped reporting the actual source
coverage.

Switch to ``coverage run -m pytest`` followed by ``coverage report``.
Running ``coverage`` from the outside means tracing starts before
Python imports anything at all, so plugin import-time code is
counted. Real source coverage jumps from ~74% to 99%; threshold goes
from 90 to 95 to reflect that.
Tests previously asserted each TestGroup field separately
(`first.selected`, `first.deselected`, `first.duration`). Consolidate
to a single equality check against an expected TestGroup, with
concrete values for every field rather than only ``selected``.
Tighten the algorithm contract so each one receives a single data
argument: a dict mapping pytest items to their durations. Promote the
helper that builds the dict to a public name (compute_durations) and
inline the two helpers that only it used.

The plugin builds the dict once and passes it to the algorithm.
Algorithm bodies otherwise consume the same (item, duration) stream
they did before, so behaviour is unchanged.

Sets up follow-ups that separate group membership from within-group
ordering.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Splits invalid when collection order not deterministic

1 participant